﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;

namespace Toolkit.Web.ViewComponents.DataGrid
{
    [DataContract]
    public sealed class ClientDataGridModel<T> where T : class
    {
        public ClientDataGridModel(DataGrid<T> dataGrid)
        {
            if (dataGrid == null)
            {
                throw new ArgumentNullException("dataGrid");
            }

            id = dataGrid.Identifier;
            loadDataAfterInitialRender = (dataGrid.DataSource == null);
            isResultSetEmpty = (dataGrid.DataSource != null && dataGrid.DataSource.Count() == 0);
            enableColumnMenus = dataGrid.Settings.EnableColumnMenus;
            enableColumnHidingAndShowing = dataGrid.Settings.EnableColumnHidingAndShowing;
            maximumNumberOfVisibleColumns = dataGrid.Settings.MaximumNumberOfVisibleColumns;
            minimumNumberOfVisibleColumns = dataGrid.Settings.MinimumNumberOfVisibleColumns;
            numberOfVisibleColumns = dataGrid.Columns.Count(column => column.Settings.IsVisible);
            numberOfVisibleColumnsWithMenu = dataGrid.Columns.Count(column => column.Settings.IsVisible && column.Settings.EnableMenu);
            renderHiddenColumns = dataGrid.Settings.RenderHiddenColumns;
            enableColumnReordering = dataGrid.Settings.EnableColumnReordering;
            enableColumnResizing = dataGrid.Settings.EnableColumnResizing;
            minimumColumnWidth = dataGrid.Settings.MinimumColumnWidth;
            maximumColumnWidth = dataGrid.Settings.MaximumColumnWidth;
            adjustColumnWidthsOnInitialDisplay = dataGrid.Settings.AdjustColumnWidthsOnInitialDisplay;
            enableColumnSorting = dataGrid.Settings.EnableColumnSorting;
            enableColumnFiltering = dataGrid.HasFilterableColumns();

            if (dataGrid.Settings.SortByColumnExpression != null)
            {
                sortByColumnExpressionEncoded = dataGrid.Settings.SortByColumnExpression.Encoded;
                sortByColumnExpressionEncrypted = dataGrid.Settings.SortByColumnExpression.Encrypted;
            }

            isSortedInDescendingOrder = dataGrid.Settings.IsSortedInDescendingOrder;
            rowHeight = dataGrid.Settings.DefaultOrSetBodyRowHeight;
            childRowHeight = dataGrid.Settings.DefaultOrSetChildRowHeight;
            enableViewPortResizing = dataGrid.Settings.EnableViewPortResizing;
            recordStartIndex = dataGrid.Settings.RecordStartIndex;
            recordSetSize = dataGrid.Settings.RecordSetSize;
            totalRecordCount = dataGrid.Settings.TotalRecordCount;
            pagingType = (int)dataGrid.Settings.PagingType;
            fieldNamePrefix = dataGrid.Settings.FieldNamePrefix;
            httpMethod = dataGrid.Settings.HttpMethod;
            enableAjaxBinding = dataGrid.Settings.EnableAjaxBinding;
            selectUrl = dataGrid.Settings.SelectUrl;
            editMode = (int)dataGrid.Settings.EditMode;
            editUrl = dataGrid.Settings.EditUrl;
            enablePersistence = dataGrid.Settings.EnablePersistence;
            persistenceKey = dataGrid.Settings.PersistenceKey;
            persistenceUrl = dataGrid.Settings.PersistenceUrl;
            includeInSelection = (dataGrid.Settings.IncludeInSelection == null) ? new List<string>() : dataGrid.Settings.IncludeInSelection;
            excludeFromSelection = (dataGrid.Settings.ExcludeFromSelection == null) ? new List<string>() : dataGrid.Settings.ExcludeFromSelection;
            includeInSelectionByDefault = dataGrid.Settings.IncludeInSelectionByDefault;

            if (dataGrid.Settings.ApplyVirtualizedScrolling)
            {
                maximumViewPortHeight = dataGrid.Settings.DefaultOrSetMaximumViewPortHeight;
            }
            else
            {
                maximumViewPortHeight = dataGrid.Settings.MaximumViewPortHeight;
            }

            int visibleIndex = 0;
            int renderedIndex = 0;
            columns = new List<ClientDataGridColumnModel<T>>();

            // Note: Must render all column models to enable column hiding and showing when render hidden columns is disabled.
            foreach (DataGridColumn<T> column in dataGrid.GetOrderedColumns())
            {
                columns.Add(new ClientDataGridColumnModel<T>(column, visibleIndex, renderedIndex));

                if (column.Settings.IsVisible)
                {
                    visibleIndex += 1;
                }

                renderedIndex += 1;
            }

            onAfterLoad = dataGrid.ClientEventHandlers.OnAfterLoad;
            onBeforeDataBind = dataGrid.ClientEventHandlers.OnBeforeDataBind;
            onDataBindOverride = dataGrid.ClientEventHandlers.OnDataBindOverride;
            onAfterDataBind = dataGrid.ClientEventHandlers.OnAfterDataBind;
            onBeforeDisplayChange = dataGrid.ClientEventHandlers.OnBeforeDisplayChange;
            onAfterDisplayChange = dataGrid.ClientEventHandlers.OnAfterDisplayChange;
            onBeforePersistData = dataGrid.ClientEventHandlers.OnBeforePersistData;
            onPersistDataOverride = dataGrid.ClientEventHandlers.OnPersistDataOverride;
            onAfterRowSelectionChange = dataGrid.ClientEventHandlers.OnAfterRowSelectionChange;
        }

        [DataMember]
        public string id
        {
            get;
            private set;
        }

        [DataMember]
        public IList<ClientDataGridColumnModel<T>> columns
        {
            get;
            private set;
        }

        [DataMember]
        public bool loadDataAfterInitialRender
        {
            get;
            private set;
        }

        [DataMember]
        public bool isResultSetEmpty
        {
            get;
            private set;
        }

        [DataMember]
        public bool enableColumnMenus
        {
            get;
            private set;
        }

        [DataMember]
        public bool enableColumnFiltering
        {
            get;
            private set;
        }

        [DataMember]
        public bool enableColumnHidingAndShowing
        {
            get;
            private set;
        }

        [DataMember]
        public int maximumNumberOfVisibleColumns
        {
            get;
            private set;
        }

        [DataMember]
        public int minimumNumberOfVisibleColumns
        {
            get;
            private set;
        }

        [DataMember]
        public int numberOfVisibleColumns
        {
            get;
            private set;
        }

        [DataMember]
        public int numberOfVisibleColumnsWithMenu
        {
            get;
            private set;
        }

        [DataMember]
        public bool renderHiddenColumns
        {
            get;
            private set;
        }

        [DataMember]
        public bool enableColumnReordering
        {
            get;
            private set;
        }

        [DataMember]
        public bool enableColumnResizing
        {
            get;
            private set;
        }

        [DataMember]
        public int minimumColumnWidth
        {
            get;
            private set;
        }

        [DataMember]
        public int maximumColumnWidth
        {
            get;
            private set;
        }

        [DataMember]
        public bool adjustColumnWidthsOnInitialDisplay
        {
            get;
            private set;
        }

        [DataMember]
        public bool enableColumnSorting
        {
            get;
            private set;
        }

        [DataMember]
        public string sortByColumnExpressionEncoded
        {
            get;
            private set;
        }

        [DataMember]
        public string sortByColumnExpressionEncrypted
        {
            get;
            private set;
        }

        [DataMember]
        public bool isSortedInDescendingOrder
        {
            get;
            private set;
        }

        [DataMember]
        public int rowHeight
        {
            get;
            private set;
        }

        [DataMember]
        public int childRowHeight
        {
            get;
            private set;
        }

        [DataMember]
        public int? maximumViewPortHeight
        {
            get;
            private set;
        }

        [DataMember]
        public bool enableViewPortResizing
        {
            get;
            private set;
        }

        [DataMember]
        public int recordStartIndex
        {
            get;
            private set;
        }

        [DataMember]
        public int? recordSetSize
        {
            get;
            private set;
        }

        [DataMember]
        public int? totalRecordCount
        {
            get;
            private set;
        }

        [DataMember]
        public int pagingType
        {
            get;
            private set;
        }

        [DataMember]
        public bool applyVirtualizedScrolling
        {
            get
            {
                return (
                    pagingType == (int)DataGridPagingType.BufferedPaging ||
                    pagingType == (int)DataGridPagingType.BufferedScrolling ||
                    pagingType == (int)DataGridPagingType.VirtualPaging
                );
            }
            private set
            {
            }
        }

        [DataMember]
        public string fieldNamePrefix
        {
            get;
            private set;
        }

        [DataMember]
        public string httpMethod
        {
            get;
            private set;
        }

        [DataMember]
        public bool enableAjaxBinding
        {
            get;
            private set;
        }

        [DataMember]
        public string selectUrl
        {
            get;
            private set;
        }

        [DataMember]
        public int editMode
        {
            get;
            private set;
        }

        [DataMember]
        public string editUrl
        {
            get;
            private set;
        }

        [DataMember]
        public bool enablePersistence
        {
            get;
            private set;
        }

        [DataMember]
        public string persistenceKey
        {
            get;
            private set;
        }

        [DataMember]
        public string persistenceUrl
        {
            get;
            private set;
        }

        [DataMember]
        public string onAfterLoad
        {
            get;
            private set;
        }

        [DataMember]
        public string onBeforeDataBind
        {
            get;
            private set;
        }

        [DataMember]
        public string onDataBindOverride
        {
            get;
            private set;
        }

        [DataMember]
        public string onAfterDataBind
        {
            get;
            private set;
        }

        [DataMember]
        public string onBeforeDisplayChange
        {
            get;
            private set;
        }

        [DataMember]
        public string onAfterDisplayChange
        {
            get;
            private set;
        }

        [DataMember]
        public string onBeforePersistData
        {
            get;
            private set;
        }

        [DataMember]
        public string onPersistDataOverride
        {
            get;
            private set;
        }

        [DataMember]
        public string onAfterRowSelectionChange
        {
            get;
            private set;
        }

        [DataMember]
        public IList<string> includeInSelection
        {
            get;
            private set;
        }

        [DataMember]
        public IList<string> excludeFromSelection
        {
            get;
            private set;
        }

        [DataMember]
        public bool includeInSelectionByDefault
        {
            get;
            private set;
        }
    }
}
